<?php

/**
 * Модель работы со страницами
 */
class PageModel extends DbModel {

    protected $_name = 'pages';

    /**
     * Получение страницы/страниц
     *
     * @param int $id #ID страницы
     * @param bool $array Указатель на возврат в виде массива
     * @return mixed
     */
    public function getPages($id = 0, $array = false) {
        if ($id > 0) {
            $select = $this->select()->where('id = ?', $id);
            $res = $this->fetchRow($select);
        } else {
            $select = $this->select();
            $res = $this->fetchAll($select);
        }
        if ($array) {
            return $res->toArray();
        } else {
            return $res;
        }
    }

    /**
     * Получение дочерних страниц по ID родителя
     *
     * @param int $id #ID страницы
     * @return mixed Дочерние страницы !!!вместе с родителем!!!
     */
    public function getChilds($id = 0) {
        $current_page = $this->getPages($id);
        if ($id > 0) {
            $select = $this->select()
                    ->where('lft >= ?', $current_page->lft)
                    ->where('rght <= ?', $current_page->rght)
                    ->order('lft DESC');
            $res = $this->fetchAll($select);
        }
        return $res;
    }

    /**
     * Получение страницы по URL
     *
     * @param string $url Ссылка страницы
     * @return array Страница, параметры
     */
    public function getPageByURL($url) {
        $pages = Zend_Registry::get('pages');
        $config = Zend_Registry::get('config');
        $pathes = explode(BASE_PATH, $url);
        unset($pathes[0]);
        $url = trim(implode(BASE_PATH, $pathes));

        $array = explode('/', trim($url, '/'));

        $links = array();
        $param = array();
        if (count($pages) == 0)
            return false;
        foreach ($pages as $page) {
            if (!isset($first))
                $first = $page;
            $links[$page->url] = $page->id;
        }
        $link = '';
        $id = 0;
        //Обходим урл
        foreach ($array as $val) {
            $link .= '/' . $val;
            if (isset($links[$link])) {
                $id = $links[$link];
                $page = $pages[$id];
            } else {
                break;
            }
        }
        //Получаем первую страницу, если существует
        if ($id == 0 && ($url == '' or $url == BASE_PATH)) {
            $page = $first;
        } elseif ($id == 0) {
            $page = $pages[$config->page404];
        }
        $controller = Zend_Controller_Front::getInstance();
        $controller->setBaseUrl($page->url);
        return $page;
    }

    /**
     * Получение первой страницы
     *
     * @return int #ID страницы
     */
    public function getFirst() {
        $select = $this->select()->from(PREFIX . 'pages', array('id', 'parent'));
        $select->order('lft ASC');
        $select->where('parent = 0');
        $select->where('visible <= 2');
        $select->limit(1);
        $res = $this->fetchRow($select);
        if (!is_null($res)) {
            $pid = $res->id;
        } else {
            $pid = 0;
        }
        return $pid;
    }

    /**
     * Получение списка страниц из реестра
     *
     * @return array Список страниц
     */
    public function getPagesList() {
        $pages = Zend_Registry::get('pages');
        if (count($pages) == 0)
            return false;
        foreach ($pages as $key => $value) {
            $list_pages[$value->id] = str_repeat("- ", $value->level) . $value->name;
        }
        return $list_pages;
    }

    /**
     * Построение дерева страниц
     *
     * @param bool $full Полный список/доступные по правам страницы
     * @return array Массив страниц с указанием уровня и прав
     */
    public function getPagesTree($full = false) {

        $select = $this->select()
                ->from(array('node' => PREFIX . $this->_name), array('node.*', 'level' => new Zend_Db_Expr('COUNT(parent.name) - 1'), 'acl' => new Zend_Db_Expr('0')))
                ->from(array('parent' => PREFIX . $this->_name), '')
                ->where('parent.lft <= node.lft')
                ->where('node.lft <= parent.rght')
                ->group('node.id')
                ->order('node.lft');
        $data = $this->fetchAll($select);
        $list_pages = array();
        $urls = array(0 => '');

        //Считываем права текущего пользователя на страницы
        $auth = Zend_Auth::getInstance();
        $config = Zend_Registry::get('config');
        $acl_model = new AclModel();
        $acls = $acl_model->getAcls('pages');
        if (!$auth->hasIdentity()) {//Если пользователь не определен берем группу ему по умолчанию
            $user_groups = array($config->group);
        } else {
            $user_groups = $acl_model->getEntry($auth->getIdentity()->id);
        }
        //print_r($user_groups);exit;
        $page_acls = array(); //Массив [группа]=максимальные права
        foreach ($acls as $key => $value) {
            if (in_array($value->gid, $user_groups)) {
                if (isset($page_acls[$value->oid])) {
                    if ($page_acls[$value->oid] < $value->acl)
                        $page_acls[$value->oid] = $value->acl;
                } else {
                    $page_acls[$value->oid] = $value->acl;
                }
            } else {
                if (!isset($page_acls[$value->oid])) {
                    $page_acls[$value->oid] = 0;
                }
            }
        }

        //Проходимся по страницам и присваиваем URL,позицию и максимальные права у текущего пользователя
        if ($data->count() > 0) {
            foreach ($data as $key => $val) {
                $pid = $val->id;

                $val->position = $val->level + 1;
                $urls[$val->level + 1] = $urls[$val->level] . '/' . $val->url;
                $val->url = $urls[$val->level] . '/' . $val->url;

                if (isset($auth->getIdentity()->id)) {
                    if ($auth->getIdentity()->id == 1) {//Если админ, то все права
                        $val->acl = 10;
                    } elseif ($val->aid == $auth->getIdentity()->id) { //Если автор страницы, полные права ему
                        $val->acl = 10;
                    } elseif (isset($page_acls[$pid])) { //Если для страницы установлены права, назначаем ей их
                        $val->acl = $page_acls[$pid];
                    } elseif (!isset($page_acls[$pid])) { //Если права не заданы даем по умолчанию на просмотр
                        $val->acl = 1;
                    }
                } elseif (isset($page_acls[$pid])) { //Если для страницы установлены права, назначаем ей их
                    $val->acl = $page_acls[$pid];
                } elseif (!isset($page_acls[$pid])) { //Если права не заданы даем по умолчанию на просмотр
                    $val->acl = 1;
                }
                $list_pages[$pid] = $val;
            }
        }

        if ($full) {
            return $list_pages;
        } else {
            /*
             * Удаляем скрытые по правам ветки
             * Оставляем только нужные уровни
             */
            $visible_pages = array();
            $visible = true;
            $visible_level = 0;
            while (list($key, $val) = each($list_pages)) {
                //Если видимости нет и уровень видимости сдвинулся влево от скрытия
                if (!$visible && $visible_level >= $val->level) {
                    $visible = true;
                }
                if ($val->acl == 0) { //Права ниже редактирования
                    $visible = false; //Убираем видимость
                    $visible_level = $val->level; //Назначаем уровень видимости
                }
                if ($visible && $val->acl > 0) {
                    $visible_pages[$key] = $list_pages[$key];
                }
            }
            //print_r($visible_pages);exit;
            return $visible_pages;
        }
    }

    /**
     * Перемещение страницы на 1 позицию
     *
     * @param int $id #ID страницы
     * @param string $action 'down' - вниз, 'up' - вверх
     */
    public function movePage($id, $action) {
        $page = $this->getPages($id);
        switch ($action) {
            case 'down':
                $select = $this->select()->from(PREFIX . 'pages', array('id', 'lft', 'rght', 'parent'))
                                ->where('lft > ' . $page->rght . ' AND parent = ' . $page->parent)
                                ->order('lft ASC')->limit(1);
                $res = $this->fetchRow($select);
                $our = 1;
                break;
            case 'up':
                $select = $this->select()->from(PREFIX . 'pages', array('id', 'lft', 'rght', 'parent'))
                                ->where('rght < ' . $page->lft . ' AND parent = ' . $page->parent)
                                ->order('lft DESC')->limit(1);
                $res = $this->fetchRow($select);
                $our = -1;
                break;
        }
        if ($res && $page->parent == $res->parent) {
            if ($action == 'up') {
                $lft = $page->lft - $res->lft;
                $rght = $page->rght - $res->rght;
                $this->update(array('rght' => new Zend_Db_Expr('-1*(rght + ' . $rght . ')'), 'lft' => new Zend_Db_Expr('-1*(lft + ' . $rght . ')')), 'lft >= ' . $res->lft . ' AND rght <= ' . $res->rght); //У обновляем делаем отрицательные индексы с новыми данными
                $this->update(array('rght' => new Zend_Db_Expr('rght - ' . $lft), 'lft' => new Zend_Db_Expr('lft - ' . $lft)), 'lft >= ' . $page->lft . ' AND rght <= ' . $page->rght);
                $this->update(array('rght' => new Zend_Db_Expr('-1*rght'), 'lft' => new Zend_Db_Expr('-1*lft')), 'lft < 0'); //Обновляем нашу страницу
            } else if ($action == 'down') {
                $lft = $res->lft - $page->lft;
                $rght = $res->rght - $page->rght;
                $this->update(array('rght' => new Zend_Db_Expr('-1*(rght - ' . $lft . ')'), 'lft' => new Zend_Db_Expr('-1*(lft - ' . $lft . ')')), 'lft >= ' . $res->lft . ' AND rght <= ' . $res->rght);
                $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $rght), 'lft' => new Zend_Db_Expr('lft + ' . $rght)), 'lft >= ' . $page->lft . ' AND rght <= ' . $page->rght);
                $this->update(array('rght' => new Zend_Db_Expr('-1*rght'), 'lft' => new Zend_Db_Expr('-1*lft')), 'lft < 0');
            }
        }
    }

    /**
     * Перемещение страницы на любую позицию
     *
     * @param int $id #ID Перемещаемой страницы
     * @param <type> $cid #ID нижней страницы
     */
    public function flyPage($id, $cid) {
        $pages = Zend_Registry::get('pages');
        $our = $pages[$id];
        $sub = false;
        if ($our->parent > 0)
            $sub = true;
        if ($cid < 1) { //Либо в самом корне, либо первая в подуровне
            if ($sub) {
                $top = $pages[$our->parent];
            } else {
                $top->rght = 0;
                $top->lft = 0;
            }
        } else {
            $top = $pages[$cid];
        }
        if (!$sub) {//Первый уровень
            $col = $our->rght - $our->lft + 1; //Кол-во едениц на которое подымаем/опускаем
            if ($our->lft < $top->lft) {
                $sum = $our->lft - $top->rght - 1 + $col;
                $down_start = $top->rght - $col; //Кол-во едениц на которое опускаем
            } else {
                $sum = $our->lft - $top->rght - 1; //Кол-во едениц для полета нашей страницы
                $down_start = $top->rght; //Кол-во едениц на которое опускаем
            }
            //Отрицаем нашу с новыми значениями
            $this->update(array('rght' => new Zend_Db_Expr('-1*(rght - ' . $sum . ')'), 'lft' => new Zend_Db_Expr('-1*(lft - ' . $sum . ')')), 'lft >= ' . $our->lft . ' AND rght <= ' . $our->rght);
            //Подымаем страницы
            $this->update(array('rght' => new Zend_Db_Expr('rght - ' . $col), 'lft' => new Zend_Db_Expr('lft - ' . $col)), 'lft > ' . $our->lft);
            //Опускаем страницы
            $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $col), 'lft' => new Zend_Db_Expr('lft + ' . $col)), 'rght > ' . $down_start);
            //Отрицаем нашу с правильными значениями
            $this->update(array('rght' => new Zend_Db_Expr('-1*rght'), 'lft' => new Zend_Db_Expr('-1*lft')), 'lft < 0');
        } else {
            $col = $our->rght - $our->lft + 1; //Кол-во едениц на которое подымаем/опускаем
            if ($our->lft < $top->lft) {//Опускаем вниз
                $sum = $our->rght - $top->rght;
            } else {//Подымаем вверх
                if ($our->rght < $top->rght) {//Вложенная
                    $sum = $our->lft - $top->lft - 1;
                } else {
                    $sum = $our->lft - $top->rght - 1;
                }
                $lft_start = $top->lft;
            }
            //Отрицаем нашу с новыми значениями
            $this->update(array('rght' => new Zend_Db_Expr('-1*(rght - ' . $sum . ')'), 'lft' => new Zend_Db_Expr('-1*(lft - ' . $sum . ')')), 'lft >= ' . $our->lft . ' AND rght <= ' . $our->rght);
            $this->update(array('rght' => new Zend_Db_Expr('rght - ' . $col), 'lft' => new Zend_Db_Expr('lft - ' . $col)), 'lft > ' . $our->lft);
            $this->update(array('rght' => new Zend_Db_Expr('rght - ' . $col)), 'lft < ' . $our->lft . ' AND rght >' . $our->rght);

            if ($our->lft > $top->lft && $our->rght < $top->rght) {//Вложенная первая
                $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $col), 'lft' => new Zend_Db_Expr('lft + ' . $col)), 'lft > ' . $lft_start);
                $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $col)), 'lft <= ' . $lft_start . ' AND rght >=' . $lft_start);
            } else {
                if ($our->lft < $top->lft) {//Опуcкаем вниз
                    $left = $top->lft - $col;
                    $right = $top->rght - $col;
                    $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $col), 'lft' => new Zend_Db_Expr('lft + ' . $col)), 'lft > ' . $left . ' AND rght > ' . $right);
                    $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $col)), 'lft <' . $left . ' AND rght >' . $right);
                } else {
                    $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $col), 'lft' => new Zend_Db_Expr('lft + ' . $col)), 'lft > ' . $top->lft . ' AND rght > ' . $top->rght);
                    $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $col)), 'lft <' . $top->lft . ' AND rght >' . $top->rght);
                }
            }

            $this->update(array('rght' => new Zend_Db_Expr('-1*rght'), 'lft' => new Zend_Db_Expr('-1*lft')), 'lft < 0');
        }
    }

    /**
     * Перемещение секции на 1 позицию
     *
     * @param int $id #ID секции
     * @param string $action 'down' - вниз, 'up' - вверх
     */
    public function moveSection($id, $action) {
        $section = $this->getSection($id);
        switch ($action) {
            case 'down':
                $select = $this->_db->select()->from(PREFIX . 'sections', array('id', 'position'))
                        ->where('position > ' . $section->position . ' AND pid = ' . $section->pid . ' AND bid = ' . $section->bid)
                        ->order('position ASC');
                $res = $this->_db->fetchRow($select);
                if ($res) {
                    $pos = $res->position;
                    $this->updateSection(array('position' => $res->position), $id);
                    $this->updateSection(array('position' => $section->position), $res->id);
                }
                break;
            case 'up':
                $select = $this->_db->select()->from(PREFIX . 'sections', array('id', 'position'))
                        ->where('position < ' . $section->position . ' AND pid = ' . $section->pid . ' AND bid = ' . $section->bid)
                        ->order('position DESC');
                $res = $this->_db->fetchRow($select);
                if ($res) {
                    $pos = $res->position;
                    $this->updateSection(array('position' => $res->position), $id);
                    $this->updateSection(array('position' => $section->position), $res->id);
                }
                break;
            case 'last':
                $select = $this->_db->select()->from(PREFIX . 'sections', array('id', 'position'))
                        ->where('pid = ' . $section->pid . ' AND bid = ' . $section->bid)
                        ->order('position DESC');
                $res = $this->_db->fetchRow($select);
                if ($res) {
                    $pos = $res->position + 1;
                    $this->updateSection(array('position' => $pos), $id);
                }
                break;
        }
    }

    /**
     * Создание/обновление свойств страницы
     *
     * @param array $data Данные страницы
     * @param int $id #ID страницы
     * @return int #ID страницы
     */
    public function updatePage($data, $id = 0) {

        if ($id > 0) { //Обновление страницы
            $page = $this->getPages($id);
            $rght = 0; //Проверка передвижения
            if ($data['parent'] == $id) { //в качестве родителя выбрали себя
                $data['parent'] = $page->parent; //меняем родителя на первоначального
                $rght = $page->rght - 2;
            } else if ($page->parent <> $data['parent']) { //выбрали другого родителя
                $sum = $page->rght - $page->lft + 1;
                $parent_page = $this->getPages($data['parent']);
                if (!($page->rght > $parent_page->rght && $page->lft < $parent_page->lft)) {//Проверка что в качестве родителя не была выбрана дочерняя страница
                    //Отрицаем индексы у нашей страницы и ее дочек
                    $this->update(array('rght' => new Zend_Db_Expr('-1*rght'), 'lft' => new Zend_Db_Expr('-1*lft')), 'lft >= ' . $page->lft . ' AND rght <= ' . $page->rght);
                    //
                    //Двигаем все страницы вверх
                    $this->update(array('rght' => new Zend_Db_Expr('rght - ' . $sum)), 'rght > ' . $page->rght);
                    $this->update(array('lft' => new Zend_Db_Expr('lft - ' . $sum)), 'lft > ' . $page->lft);
                    if ($data['parent'] > 0) {
                        $parent_page = $this->getPages($data['parent']);
                        $sum_move = $page->rght - ($parent_page->rght + $sum) + 1;
                        //echo($sum.'//'.$sum_move.'//'.$parent_page->rght);exit;
                        //Высвобождаем место для наших страниц
                        $this->update(array('lft' => new Zend_Db_Expr('lft + ' . $sum)), 'lft > ' . $parent_page->lft . ' AND rght > ' . $parent_page->rght);
                        $this->update(array('rght' => new Zend_Db_Expr('rght + ' . $sum)), 'rght >= ' . $parent_page->rght);

                        //Обновляем индексы у нашей страницы
                        $this->update(array('rght' => new Zend_Db_Expr('-1*rght - ' . $sum_move), 'lft' => new Zend_Db_Expr('-1*lft - ' . $sum_move)), 'lft < 0');
                    } else {
                        $select = $this->select()->from(PREFIX . 'pages', array('max' => new Zend_Db_Expr('MAX(rght)')));
                        $res = $this->fetchRow($select);
                        $sum_move = $res->max - $page->lft + 1;
                        //echo($sum_move);exit;
                        $this->update(array('rght' => new Zend_Db_Expr('-1*rght + ' . $sum_move), 'lft' => new Zend_Db_Expr('-1*lft + ' . $sum_move)), 'lft < 0');
                    }
                } else {
                    $data['parent'] = $page->parent; //Меняем родителя на старого
                }
            }
            //if ($rght <> 0) $data = $data + array('lft'=>$rght + 1,'rght'=>$rght + 2);
            $this->update($data, "id = " . $id);
            return $id;
        } else { //Создание новой страницы
            //Смотрим последний узел по родителю
            $pid = $data['parent'];
            $select = $this->select()->where('parent = ?', $pid)
                            ->order('rght DESC')->limit(1);
            $res = $this->_db->fetchRow($select);
            if (!$res) { //Дочерних узлов нет
                if ($pid == 0) {//Вообще узлов нет, наш самый первый
                    $rght = 0;
                } else {//Наш узел первый у родителя
                    $select = $this->select()->where('id = ?', $pid);
                    $res = $this->_db->fetchRow($select);
                    $rght = $res->lft;
                }
            } else {
                $rght = $res->rght;
            }
            $this->update(array('rght' => new Zend_Db_Expr('rght + 2')), 'rght > ' . $rght);
            $this->update(array('lft' => new Zend_Db_Expr('lft + 2')), 'lft > ' . $rght);
            $this->insert($data + array('lft' => $rght + 1, 'rght' => $rght + 2));
            $pid = $this->_db->lastInsertId();

            $session = new Zend_Session_Namespace('UnCMS');
            $groups = $session->groups;

            /*
              foreach ($groups as $key => $value)
              $groups[$key] = 1;
              if (isset($groups[1]))
              $groups[2] = 3;
              $aclModel = new AclModel();
              $aclModel->updateAcls('pages', $pid, $groups);
             */

            return $pid;
        }
    }

    /**
     * Удаление страницы по ID
     *
     * @param int $pid #ID страницы
     */
    public function deletePage($pid = 0) {
        $page = $this->getPages($pid);
        $rght = $page->rght;
        //сдвигаем все левее
        $this->update(array('rght' => new Zend_Db_Expr('rght - 2')), 'rght > ' . $rght);
        $this->update(array('lft' => new Zend_Db_Expr('lft - 2')), 'lft > ' . $rght);
        //Удаляем нашу страницу
        $this->delete('id = ' . $pid);
    }

    /**
     * Получение списка дополнений
     *
     * @param string $type Тип дополнения
     * @param id $id #ID дополнения
     * @return mixed Список дополнений
     */
    public function getAddons($type = '', $id = 0) {
        $db = $this->_db;
        if ($type <> '') {
            $select = $db->select()->from(PREFIX . 'addons')->where('type = ?', $type)->order('name');
        } else {
            $select = $db->select()->from(PREFIX . 'addons')->order('name');
        }
        if ($id > 0) {
            $select->where('id = ?', $id);
            $res = $db->fetchRow($select);
        } else {
            $res = $db->fetchAll($select);
        }
        return $res;
    }

    /**
     * Получение списка дополнений в виде массива
     *
     * @param string $type Тип дополнения
     * @param string $col 2 возвращаемый столбец после id
     * @return mixed Список дополнений
     */
    public function getAddonsList($type = '', $col = 'name') {
        $db = $this->_db;
        if ($type <> '') {
            $select = $db->select()->from(PREFIX . 'addons', array('id', $col))->where('type = ?', $type)->order($col . ' ASC');
            if ($type == 'template') {
                $select->where("title <> 'default'");
            }
        } else {
            $select = $db->select()->from(PREFIX . 'addons', array('id', $col))->order($col . ' ASC');
        }
        $res = $db->fetchPairs($select);
        return $res;
    }

    public function getModulesList() {
        $db = $this->_db;
        $select = $db->select()->from(PREFIX . 'addons')->where('type = "page"')->order('name ASC');
        $res = $db->fetchAll($select);
        $modules_list = array();
        $session = new Zend_Session_Namespace('UnCMS');
        foreach ($res as $value) {
            if (isset($session->acl->{$value->title}))
                $modules_list[$value->id] = $value->name;
        }
        return $modules_list;
    }

    /**
     * Добавление секции
     *
     * @param array $data Свойства секции
     * @return int #ID секции
     */
    public function addSection($data) {
        $select = $this->_db->insert(PREFIX . 'sections', $data);
        $id = $this->_db->lastInsertId();
        $this->moveSection($id, 'last');
        return $id;
    }

    /**
     * Обновление/добавление секции
     *
     * @param array $data Свойства секции
     * @return int #ID секции
     */
    public function updateSection($data, $id = 0) {
        if ($id > 0) {
            $this->_db->update(PREFIX . 'sections', $data, "id = " . $id);
            return $id;
        } else {
            $id = $this->addSection($data);
            return $id;
        }
    }

    /**
     * Удаление секции по ID
     *
     * @param int $id #ID секции
     * @return int #ID удаленной секции
     */
    public function deleteSection($id) {
        $db = $this->_db;
        $sid = (int) $id;
        if ($sid > 0) {
            $section = $this->getSection($sid);
            $module = $this->getAddons('page', $section->mid);
            $module_model_name = ucfirst($module->title . 'Model');
            $module_model = new $module_model_name();
            $module_model->deleteSection($sid);
            $this->_db->delete(PREFIX . 'sections', 'id =' . $sid);
        }
        return $id;
    }

    /**
     * Получение блоков страницы по её шаблону
     *
     * @param int $id #ID страницы
     * @return array Блоки
     */
    public function getBlocks($id = 0) {
        $db = $this->_db;
        if ($id > 0) {
            $tid = $this->getPages($id)->template;
            if ($tid > 0) {
                $template = $this->getAddons('template', $tid);
                $template_title = $template->title;
            } else {
                $config = Zend_Registry::get('config');
                $template_title = $config->template;
            }
            $block = array();
            include(APP_PATH . '/templates/' . $template_title . '/info.php');
            $res = $block;
            return $res;
        }
    }

    /**
     * Получение секций
     *
     * @param int $pid #ID страницы
     * @param bool $main Только главный блок
     * @return mixed
     */
    public function getSections($pid = 0, $main = false) {
        $db = $this->_db;
        if ($pid > 0) {
            $select = $db->select()->from(PREFIX . 'sections')
                    ->where('pid =?', $pid)
                    ->order('bid ASC')
                    ->order('position ASC');
            if ($main) {
                $select->where('bid = ?', 0);
            }
            $res = $db->fetchAll($select);
            return $res;
        }
    }

    /**
     * Получение секций (Списки)
     *
     * @param int $pid #ID страницы
     * @param bool $main Только главный блок
     * @return mixed
     */
    public function getSectionsList($pid = 0, $main = false) {
        $db = $this->_db;
        if ($pid > 0) {
            $select = $db->select()->from(PREFIX . 'sections', array('id', 'name'))
                    ->where('pid =?', $pid)
                    ->order('bid ASC')
                    ->order('position ASC');
            if ($main) {
                $select->where('bid = ?', 0);
            }
            $res = $db->fetchPairs($select);
            return $res;
        }
    }

    /**
     * Получение секции
     *
     * @param int $id #ID секции
     * @return object Секия
     */
    public function getSection($id = 0) {
        $db = $this->_db;
        if ($id > 0) {
            $select = $db->select()->from(PREFIX . 'sections')
                    ->where('id =?', $id);
            $res = $db->fetchRow($select);
            return $res;
        }
    }

    /**
     * Замена внутренних ссылок
     *
     * @param string $content Содержание
     * @return string Отформатированное содержание
     */
    public function replaceLinks($content) {
        $pages = Zend_Registry::get('pages');
        $pattern = '/\{{{PAGE_(.+?)\}}}/s';
        preg_match_all($pattern, $content, $ids);
        foreach ($ids[1] AS $page_id) {
            $pattern = '/\{{{PAGE_' . $page_id . '\}}}/s';
            if (isset($pages[$page_id])) {
                $page = $pages[$page_id];
                $link = $page->url;
                $content = preg_replace($pattern, $link, $content);
            }
        }
        return $content;
    }

    /**
     * Получение меню для сайта
     *
     * @param  integer $parent Родительская страница
     * @param  integer $start_level Стартовый уровень
     * @param  integer $end_level Максимальный уровень
     * @param  string $class UL.class
     * @param  string $id UL#id
     * @param  int $max_visible Признак видимости 0 - видимые,2 скрытые, 4 невидимые
     * @param  bool $xml Признак формирования sitemap.xml
     * @return string
     */
    public function showMenu($parent = 0, $start_level = 0, $end_level = 100, $class = '', $id = '', $max_visible = 1, $xml = false) {
        $pages = Zend_Registry::get('pages');
        /*
         * Формируем меню
         */
        $menu = '';
        $prelevel = 0;

        //Если задана родительская страница, то извлекаем только ее дочек
        if ($parent > 0) {
            $childs_pages = array();
            $start_add = false;
            while (list($key, $val) = each($pages)) {
                if ($start_add && $val->level <= $parent_level)
                    $start_add = false;
                if ($start_add)
                    $childs_pages[$key] = $pages[$key];
                if ($key == $parent) {
                    $start_add = true;
                    $parent_level = $pages[$parent]->level;
                }
            }
            $pages = $childs_pages;
        }
        /*
         * Удаляем скрытые ветки
         * Оставляем только нужные уровни
         */
        $visible_pages = array();
        $visible = true;
        while (list($key, $val) = each($pages)) {
            //Если видимости нет и уровень видимости сдвинулся влево от скрытия
            if (!$visible && $visible_level >= $val->level)
                $visible = true;
            if ($val->visible > $max_visible || $val->acl == 0) { //Cкрытая страница и нет на нее никаких прав
                $visible = false; //Убираем видимость
                $visible_level = $val->level; //Назначаем уровень видимости
            }
            if ($visible && $val->level >= $start_level && $val->level <= $end_level && $val->acl > 0)
                $visible_pages[$key] = $pages[$key];
        }

        /*
         * Прогоняем массив в обратном порядке для формирования последних позиций
         * и развернутости
         */

        //Развернутость по родителю
        $expand_array = array();
        for ($i = 1; $i < 100; $i++) {
            if ($i == 1)
                $key = PAGE_ID;
            if (isset($pages[$key]['parent']) && $pages[$key]['parent'] > 0) {
                $parent_id = $pages[$key]['parent'];
                $expand_array[$parent_id] = $parent_id;
            } else {
                break;
            }
        }

        //Последний в ветке
        $revers_pages = array_reverse($visible_pages, true);
        $last_array = array();
        $levels = array();
        while (list($key, $val) = each($revers_pages)) {
            if (!isset($levels[$val->level])) {
                $levels[$val->level] = 1;
                $last_array[$key] = $val->name;
                if (isset($levels[$val->level + 1])) {
                    unset($levels[$val->level + 1]);
                }
            }
        }
        //В формате XML либо HTML
        if ($xml) {
            $dom = new DomDocument('1.0', 'utf-8');
            $urlset = $dom->appendChild($dom->createElement('urlset'));
            $urlset->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
            $urlset->setAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd');
            $urlset->setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
            while (list($key, $val) = each($visible_pages)) {
                if ($val->visible <> -1) {
                    $lastmod_value = date('Y-m-d', strtotime($val->timestamp));
                    $url = $urlset->appendChild($dom->createElement('url'));
                    $loc = $url->appendChild($dom->createElement('loc'));
                    $lastmod = $url->appendChild($dom->createElement('lastmod'));
                    $changefreq = $url->appendChild($dom->createElement('changefreq'));
                    $priority = $url->appendChild($dom->createElement('priority'));
                    $loc->appendChild($dom->createTextNode(SITE_URL . $val->url . '/'));
                    $lastmod->appendChild($dom->createTextNode($lastmod_value));
                    $changefreq->appendChild($dom->createTextNode('monthly'));
                    $priority->appendChild($dom->createTextNode('0.5'));
                }
            }
            return $dom->saveXML();
        } else {
            while (list($key, $val) = each($visible_pages)) {
                /* Создаем начала списка XHTML */
                $pos = $val->level + 1; //текущий уровень страницы
                $css = ""; //Обнуляем стиль
                if ($prelevel > $pos)
                    $menu .= str_repeat('</li></ul>', $prelevel - $pos);
                if ($prelevel >= $pos) {
                    $menu .= '</li>';
                }
                if ($prelevel < $pos) {
                    $css .= 'menu_first ';
                    if ($prelevel == 0) {//Начало всего списка
                        $menu .= '<ul id="' . $id . '" class="' . $class . '">';
                    } else {
                        $menu .= '<ul>';
                    }
                }
                $prelevel = $pos;
                // Проверка на последнюю позицию
                if (isset($last_array[$val->id]))
                    $css .= 'menu_last ';
                if (isset($expand_array[$val->id]))
                    $css .= 'menu_expand ';
                //Проверка на текущую страницу
                if ($val->id == PAGE_ID)
                    $css .= 'menu_current ';
                $css = trim($css);

                if ($val->visible <> -1) {
                    $menu .= '<li class="' . $css . '"><a href="' . SITE_URL . $val->url . '"><span>' . $val->name . '</span></a>';
                } else {
                    if ($val->blank) {
                        $menu .= '<li class="' . $css . '"><a href="' . $val->link . '" target="_blank"><span>' . $val->name . '</span></a>';
                    } else {
                        $menu .= '<li class="' . $css . '"><a href="' . $val->link . '"><span>' . $val->name . '</span></a>';
                    }
                }
            }
            if ($visible_pages) {
                $menu .= '</li>' . str_repeat('</ul>', $prelevel);
            }
            return $menu;
        }
    }

    /**
     * Получение хлебных крошек
     *
     * @param string $class UL.class
     * @param string $del Разделитель
     * @return string
     */
    public function Breadcrumbs($class = '', $del = '&nbsp;→&nbsp;') {
        $pages = Zend_Registry::get('pages');
        $registerBreadcrumbs = Zend_Registry::get('breadcrumbs');
        $mainPage = current($pages);
        if ($mainPage->id == PAGE_ID)
            return null;
        $breadcrumbs = array();
        $string = '';
        $curr = $pages[PAGE_ID];

        $breadcrumbs[0] = array('url' => $curr->url, 'name' => $curr->name);
        for ($i = 1; $i < 100; $i++) {
            if ($curr->parent == 0) {
                break;
            } else {
                $curr = $pages[$curr->parent];
                if ($curr->visible == -1)
                    $curr->url = $curr->link;
                $breadcrumbs[$i] = array('url' => $curr->url, 'name' => $curr->name, 'blank' => $curr->blank);
            }
        }
        $breadcrumbs = array_merge($registerBreadcrumbs, $breadcrumbs);
        $result = array_reverse($breadcrumbs);
        $t = Zend_Registry::get('Zend_Locale');
        $count = count($result);
        if ($count > 0) {
            $string = '<div class="' . $class . '"><ul>';
            $string .= '<li><a href="/">' . $t->_('Home') . '</a>' . $del . '</li>';
            $i = 0;
            foreach ($result as $v) {
                $i++;
                if ($i == $count) {
                    $string .= '<li>' . $v['name'] . '</li>';
                } else {
                    if (isset($v['blank']) && $v['blank'] == 1)
                        $string .= '<li><a href="' . $v['url'] . '" target="_blank">' . $v['name'] . '</a>' . $del . '</li>';
                    else
                        $string .= '<li><a href="' . $v['url'] . '">' . $v['name'] . '</a>' . $del . '</li>';
                }
            }
            $string .= '</ul></div>';
        }
        return $string;
    }

    /**
     * Обновление времени последнего редактирования страницы
     *
     * @param int $pid #ID страницы
     */
    function updateTime($pid) {
        $this->update(array('timestamp' => date('Y-m-d H:i:s')), 'id = ' . $pid);
    }

}